/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [Example_05_Reflection_Generics.java]
 * Creation Date        [30-Jun-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_07_generics;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.Scanner;

/**
 * 反射和泛型
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class Example_05_Reflection_Generics {

	/**
	 * 获得指定类的所有属性(包括私有属性)
	 * 
	 * @param classType
	 *            指定类的类型
	 */
	public static void listField(Class<?> classType) {
		Field[] fields = classType.getDeclaredFields();
		for (Field field : fields) {
			System.out.print("    ");
			// 获得属性修饰符
			String modifier = Modifier.toString(field.getModifiers());
			// 获得属性类型
			String fieldType = field.getType().getSimpleName();
			// 获得属性名称
			String fieldName = field.getName();
			System.out.println(modifier + " " + fieldType + " " + fieldName
					+ ";");
		}
	}

	/**
	 * 获得指定类的所有方法
	 * 
	 * @param classType
	 *            指定类的类型
	 */
	public static void listMethod(Class<?> classType) {
		Method[] methods = classType.getDeclaredMethods();
		for (Method method : methods) {
			System.out.print("    ");
			// 获得方法名称
			String methodName = method.getName();
			// 获得方法修饰符
			String modifier = Modifier.toString(method.getModifiers());

			if (modifier.length() > 0) {
				System.out.print(modifier);
			}

			// 获得泛型方法类型
			Example_05_Reflection_Generics.printTypes(
					method.getTypeParameters(), " <", ",", ">", true);
			System.out.print(" ");

			// 获得方法的返回类型
			Type returnType = method.getGenericReturnType();
			Example_05_Reflection_Generics.printTypes(returnType, false);
			System.out.print(" " + methodName + "(");

			// 获得方法的参数类型
			Type[] paramTypes = method.getGenericParameterTypes();
			for (int i = 0; i < paramTypes.length; i++) {
				if (i > 0) {
					System.out.print(", ");
				}

				// 获得参数类型
				Example_05_Reflection_Generics.printTypes(paramTypes[i], false);
				System.out.print(" " + "param" + i);
			}
			System.out.print(") ");

			// 获得方法抛出的异常
			Type[] exceptionTypes = method.getGenericExceptionTypes();
			if (exceptionTypes.length > 0) {
				System.out.print("throws ");
			}
			for (int i = 0; i < exceptionTypes.length; i++) {
				if (i > 0) {
					System.out.print(",");
				}
				Example_05_Reflection_Generics.printTypes(exceptionTypes[i],
						false);
			}
			System.out.println("{}");
		}
	}

	/**
	 * 获得指定类的所有构造器
	 * 
	 * @param classType
	 *            指定类的类型
	 */
	public static void listConstructor(Class<?> classType) {
		Constructor<?>[] constructors = classType.getDeclaredConstructors();

		for (Constructor<?> constructor : constructors) {
			System.out.print("    ");
			// 获得构造器的名称, 去掉多余的包名
			String name = constructor.getName();
			String[] names = name.split("\\.");
			String realName = names[names.length - 1];

			// 获得构造器的修饰符
			String modifier = Modifier.toString(constructor.getModifiers());
			if (modifier.length() > 0) {
				System.out.print(modifier + " ");
			}

			System.out.print(realName + "(");

			// 获得构造器的参数类型
			Type[] paramTypes = constructor.getGenericParameterTypes();
			for (int i = 0; i < paramTypes.length; i++) {
				if (i > 0) {
					System.out.print(", ");
				}
				Example_05_Reflection_Generics.printTypes(paramTypes[i], false);
				System.out.print(" " + "param" + i);
			}
			System.out.print(")");

			// 获得方法抛出的异常
			Type[] exceptionTypes = constructor.getGenericExceptionTypes();
			if (exceptionTypes.length > 0) {
				System.out.print("throws ");
			}
			for (int i = 0; i < exceptionTypes.length; i++) {
				if (i > 0) {
					System.out.print(",");
				}
				Example_05_Reflection_Generics.printTypes(exceptionTypes[i],
						false);
			}
			System.out.println("{}");
		}
	}

	/**
	 * 打印类型参数
	 * 
	 * @param types
	 *            类型参数
	 * @param prefix
	 *            前缀
	 * @param seperator
	 *            分隔符
	 * @param suffix
	 *            后缀
	 * @param isDefinition
	 *            是否定义
	 */
	private static void printTypes(Type[] types, String prefix,
			String seperator, String suffix, boolean isDefinition) {
		// 如果继承的是Object类, 不打印信息
		if (prefix.equals(" extends ")
				&& Arrays.equals(types, new Type[] { Object.class })) {
			return;
		}
		if (types.length > 0) {
			System.out.print(prefix);
		}
		for (int i = 0; i < types.length; i++) {
			if (i > 0) {
				System.out.print(seperator);
			}
			Example_05_Reflection_Generics.printTypes(types[i], isDefinition);
		}
		if (types.length > 0) {
			System.out.print(suffix);
		}
	}

	/**
	 * 打印类型参数
	 * 
	 * @param type
	 *            类型参数
	 * @param isDefinition
	 *            是否定义
	 */
	@SuppressWarnings("rawtypes")
	private static void printTypes(Type type, boolean isDefinition) {
		if (type instanceof Class) {
			Class<?> t = (Class<?>) type;
			System.out.print(t.getSimpleName());
		} else if (type instanceof TypeVariable) {
			TypeVariable t = (TypeVariable) type;
			System.out.print(t.getName());
			if (isDefinition) {
				Example_05_Reflection_Generics.printTypes(t.getBounds(),
						" extends ", " & ", "", false);
			}
		} else if (type instanceof WildcardType) {
			WildcardType t = (WildcardType) type;
			System.out.print("?");
			Example_05_Reflection_Generics.printTypes(t.getUpperBounds(),
					" extends ", " & ", "", false);
			Example_05_Reflection_Generics.printTypes(t.getLowerBounds(),
					" super ", " & ", "", false);
		} else if (type instanceof ParameterizedType) {
			ParameterizedType t = (ParameterizedType) type;
			Type owner = t.getOwnerType();
			if (owner != null) {
				Example_05_Reflection_Generics.printTypes(owner, false);
				System.out.print(".");
			}
			Example_05_Reflection_Generics.printTypes(t.getRawType(), false);
			Example_05_Reflection_Generics.printTypes(
					t.getActualTypeArguments(), "<", ",", ">", false);
		} else if (type instanceof GenericArrayType) {
			GenericArrayType t = (GenericArrayType) type;
			System.out.print("");
			Example_05_Reflection_Generics.printTypes(
					t.getGenericComponentType(), isDefinition);
			System.out.print("[]");
		}
	}

	/**
	 * 测试方法
	 * 
	 * @param args
	 *            命令行参数
	 */
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入完整的类名:例如java.util.Scanner");
		String className = scanner.next();
		scanner.close();
		try {
			Class<?> classType = Class.forName(className);
			// 获得类的修饰符
			String modifiers = Modifier.toString(classType.getModifiers());
			if (modifiers.length() > 0) {
				System.out.print(modifiers + " ");
			}
			System.out.print("class " + classType.getSimpleName());

			// 打印泛型参数
			Example_05_Reflection_Generics.printTypes(
					classType.getTypeParameters(), "<", ",", ">", true);

			// 打印继承的类
			Type type = classType.getGenericSuperclass();
			if (type != null) {
				System.out.print(" extends ");
				Example_05_Reflection_Generics.printTypes(type, false);
			}

			// 打印实现的接口
			Example_05_Reflection_Generics.printTypes(
					classType.getGenericInterfaces(), " implements ", ", ", "",
					false);

			System.out.println(" {");

			Example_05_Reflection_Generics.listField(classType);
			Example_05_Reflection_Generics.listConstructor(classType);
			Example_05_Reflection_Generics.listMethod(classType);

			System.out.print("}");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}
